package com.ruoyi.web.controller.shop.service.Impl;

import com.ruoyi.common.constant.CouponConstants;
import com.ruoyi.common.constant.LianLuSmsConstants;
import com.ruoyi.common.constant.SysConfigConstants;
import com.ruoyi.common.entity.DO.marketing.CouponDO;
import com.ruoyi.common.entity.DO.member.MemberCouponDO;
import com.ruoyi.common.entity.DO.member.MemberDO;
import com.ruoyi.common.entity.DO.product.ShopProductCouponLinkDO;
import com.ruoyi.common.entity.VO.CouponSearchVO;
import com.ruoyi.common.entity.VO.CouponVO;
import com.ruoyi.common.entity.VO.member.MemberCouponVO;
import com.ruoyi.common.entity.VO.member.MemberGetCouponVO;
import com.ruoyi.common.entity.VO.shop.ShopProductSearchVO;
import com.ruoyi.common.entity.VO.shop.ShopProductVO;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.web.controller.member.mapper.IBackMemberCouponMapper;
import com.ruoyi.web.controller.member.mapper.IBackMemberMapper;
import com.ruoyi.web.controller.shop.mapper.IBackShopCouponMapper;
import com.ruoyi.web.controller.shop.mapper.IBackShopProductCouponLinkMapper;
import com.ruoyi.web.controller.shop.service.IBackShopCouponService;
import com.ruoyi.web.controller.shop.service.IBackShopProductService;
import lombok.Synchronized;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

@Service
public class BackShopCouponServiceImpl implements IBackShopCouponService {

    @Resource
    private IBackShopProductService backShopProductService;

    @Resource
    private IBackShopCouponMapper backShopCouponMapper;

    @Resource
    private IBackMemberMapper backMemberMapper;

    @Resource
    private IBackMemberCouponMapper backMemberCouponMapper;

    @Resource
    private IBackShopProductCouponLinkMapper backShopProductCouponLinkMapper;

    @Override
    public List<CouponVO> searchList(CouponSearchVO searchVO) {
        searchVO.setIsDelete(0);
        List<CouponVO> couponList = backShopCouponMapper.searchList(searchVO);
        for (CouponVO one : couponList
        ) {
            if (one.getCouponType() == CouponConstants.TypeEnum.DISCOUNT.getValue()) {
                one.setDiscountValue(one.getDiscount().multiply(BigDecimal.TEN).setScale(1, BigDecimal.ROUND_DOWN));
            }
        }
        return couponList;
    }

    @Override
    public List<MemberCouponVO> searchMemberList(CouponSearchVO searchVO) {
        searchVO.setIsDelete(0);
        List<MemberCouponVO> couponList = backMemberCouponMapper.searchMemberCouponList(searchVO);
        for (MemberCouponVO one : couponList
        ) {
            if (one.getCouponType() == CouponConstants.TypeEnum.DISCOUNT.getValue()) {
                one.setDiscountValue(one.getDiscount().multiply(BigDecimal.TEN).setScale(1, BigDecimal.ROUND_DOWN));
            }
        }
        return couponList;
    }

    @Override
    public CouponVO getInfoById(Long couponId) {
        return backShopCouponMapper.getInfoById(couponId);
    }

    @Override
    public String checkCouponTitleUnique(CouponVO couponVO) {
        return null;
    }

    @Override
    @Transactional
    public int insertCoupon(CouponVO couponVO) {
        CouponDO newCoupon = new CouponDO();
        BeanUtils.copyProperties(couponVO, newCoupon);
        newCoupon.setStock(newCoupon.getTotalIssuance());
        newCoupon.setTotalGet(0);
        newCoupon.setTotalMemberGet(0);
        newCoupon.setTotalUse(0);
        newCoupon.setModuleType(SysConfigConstants.SystemModuleEnum.PETROL.getValue());
        newCoupon.setCreateTime(new Date());
        if (DateUtils.getNowDate().getTime() > newCoupon.getUseStartTime().getTime()) {
            newCoupon.setCouponStatus(CouponConstants.CouponStatusEnum.AVAILABLE.getValue());
        } else {
            newCoupon.setCouponStatus(CouponConstants.CouponStatusEnum.WAIT.getValue());
        }
        if (DateUtils.getNowDate().getTime() > newCoupon.getUseEndTime().getTime()) {
            newCoupon.setCouponStatus(CouponConstants.CouponStatusEnum.EXPIRED.getValue());
        }
        backShopCouponMapper.insertSelective(newCoupon);
        if (null != couponVO.getProductIdArr() && couponVO.getProductIdArr().length > 0) {
            ShopProductSearchVO searchVO = new ShopProductSearchVO();
            searchVO.setShopId(ShiroUtils.getShopId());
            searchVO.setSystemModule(SysConfigConstants.SystemModuleEnum.PETROL.getValue());
            searchVO.setIsEnable(1);
            searchVO.setIsDelete(0);
            searchVO.setProductIdStr(StringUtils.join(couponVO.getProductIdArr(), ","));
            List<ShopProductVO> petrolList = backShopProductService.searchList(searchVO);
            if (petrolList.size() != couponVO.getProductIdArr().length) {
                throw new BusinessException("所选适用油品无效！");
            }
            StringBuilder linkProductStr = new StringBuilder();
            //插入油品关联表
            for (Long productId : couponVO.getProductIdArr()
            ) {
                for (ShopProductVO one : petrolList
                ) {
                    if (one.getProductId().equals(productId)) {
                        linkProductStr.append(one.getProductCategory()).append(one.getProductName()).append(",");
                        ShopProductCouponLinkDO couponLinkDO = new ShopProductCouponLinkDO();
                        couponLinkDO.setCouponId(newCoupon.getId());
                        couponLinkDO.setProductId(productId);
                        couponLinkDO.setShopId(couponVO.getShopId());
                        couponLinkDO.setModuleId(SysConfigConstants.SystemModuleEnum.PETROL.getValue());
                        backShopProductCouponLinkMapper.insertSelective(couponLinkDO);
                    }

                }
            }
            CouponDO couponUpdate = new CouponDO();
            couponUpdate.setId(newCoupon.getId());
            couponUpdate.setLinkProduct(linkProductStr.substring(0, linkProductStr.length() - 1));
            backShopCouponMapper.updateByPrimaryKeySelective(couponUpdate);
        }
        return 1;
    }

    @Override
    @Transactional
    @Synchronized
    public int updateCoupon(CouponVO couponVO) {
        CouponDO couponDO = backShopCouponMapper.selectByPrimaryKey(couponVO.getId());
        if (couponDO == null || couponDO.getIsDelete() == 1) {
            throw new BusinessException("优惠券已删除，请刷新后重试！");
        }
        if (couponVO.getTotalIssuance() < couponDO.getTotalGet()) {
            throw new BusinessException("总发放数量不能少于已领取数量！");
        }
        couponDO.setTotalIssuance(couponVO.getTotalIssuance());
        couponDO.setStock(couponDO.getTotalIssuance() - couponDO.getTotalGet());
        couponDO.setIsEnable(couponVO.getIsEnable());
        couponDO.setIsAbleActivity(couponVO.getIsAbleActivity());
        couponDO.setUseStartTime(couponVO.getUseStartTime());
        couponDO.setUseEndTime(couponVO.getUseEndTime());
        if (DateUtils.getNowDate().getTime() > couponDO.getUseStartTime().getTime()) {
            if (couponDO.getStock() == 0) {
                couponDO.setCouponStatus(CouponConstants.CouponStatusEnum.FINISH.getValue());
            } else {
                couponDO.setCouponStatus(CouponConstants.CouponStatusEnum.AVAILABLE.getValue());
            }
        } else {
            couponDO.setCouponStatus(CouponConstants.CouponStatusEnum.WAIT.getValue());
        }
        if (DateUtils.getNowDate().getTime() > couponDO.getUseEndTime().getTime()) {
            couponDO.setCouponStatus(CouponConstants.CouponStatusEnum.EXPIRED.getValue());
        }
        couponDO.setLinkProduct("");
        backShopProductCouponLinkMapper.clearByCouponId(couponDO.getShopId(), couponDO.getId());
        if (null != couponVO.getProductIdArr() && couponVO.getProductIdArr().length > 0) {
            ShopProductSearchVO searchVO = new ShopProductSearchVO();
            searchVO.setShopId(couponDO.getShopId());
            searchVO.setSystemModule(SysConfigConstants.SystemModuleEnum.PETROL.getValue());
            searchVO.setIsEnable(1);
            searchVO.setIsDelete(0);
            searchVO.setProductIdStr(StringUtils.join(couponVO.getProductIdArr(), ","));
            List<ShopProductVO> petrolList = backShopProductService.searchList(searchVO);
            if (petrolList.size() != couponVO.getProductIdArr().length) {
                throw new BusinessException("所选适用油品无效！");
            }
            StringBuilder linkProductStr = new StringBuilder();
            //插入油品关联表
            for (Long productId : couponVO.getProductIdArr()
            ) {
                for (ShopProductVO one : petrolList
                ) {
                    if (one.getProductId().equals(productId)) {
                        linkProductStr.append(one.getProductCategory()).append(one.getProductName()).append(",");
                        ShopProductCouponLinkDO couponLinkDO = new ShopProductCouponLinkDO();
                        couponLinkDO.setCouponId(couponDO.getId());
                        couponLinkDO.setProductId(productId);
                        couponLinkDO.setShopId(couponVO.getShopId());
                        couponLinkDO.setModuleId(SysConfigConstants.SystemModuleEnum.PETROL.getValue());
                        backShopProductCouponLinkMapper.insertSelective(couponLinkDO);
                    }

                }
            }
            couponDO.setLinkProduct(linkProductStr.substring(0, linkProductStr.length() - 1));
        }
        return backShopCouponMapper.updateByPrimaryKeySelective(couponDO);
    }

    @Override
    public int deleteCouponById(Long shopId, Long id) {
        CouponDO couponDO = backShopCouponMapper.selectByPrimaryKey(id);
        if (couponDO == null || couponDO.getIsDelete() == 1) {
            throw new BusinessException("优惠券已删除，请刷新后重试！");
        }
        if (1 == couponDO.getIsEnable()) {
            throw new BusinessException("请先下架该优惠券！");
        }
        if (couponDO.getTotalGet() > 0) {
            throw new BusinessException("已有会员领取该优惠券，无法删除！");
        }
        return backShopCouponMapper.remove(id);
    }

    @Override
    @Transactional
    @Synchronized
    public void sendToMember(MemberGetCouponVO memberGetCouponVO) {
        //获取待赠送优惠券列表
        CouponSearchVO searchVO = new CouponSearchVO();
        searchVO.setIsDelete(0);
        searchVO.setIsEnable(1);
        searchVO.setCouponStatus(CouponConstants.CouponStatusEnum.AVAILABLE.getValue());
        searchVO.setCouponIdStr(memberGetCouponVO.getCouponIdStr());
        String[] couponIdArr = memberGetCouponVO.getCouponIdStr().split(",");
        List<CouponVO> couponList = backShopCouponMapper.searchList(searchVO);
        if (couponIdArr.length != couponList.size()) {
            throw new BusinessException("存在不符合可赠送状态的优惠券，请刷新后重试！");
        }
        List<MemberDO> memberList = backMemberMapper.searchListByIdStr(memberGetCouponVO.getMemberIdStr());
        String[] memberIdArr = memberGetCouponVO.getMemberIdStr().split(",");
        if (memberIdArr.length != memberList.size()) {
            throw new BusinessException("存在不符合受赠状态的会员，请刷新后重试！");
        }
        List<MemberCouponDO> preInsertList = new ArrayList<>();
        List<HashMap<String, String>> wxNotifyParamList = new ArrayList<>();
        List<HashMap<String, String>> smsNotifyParamList = new ArrayList<>();
        for (CouponVO couponOne : couponList
        ) {
            if (couponOne.getStock() < memberIdArr.length) {
                throw new BusinessException("优惠券【" + couponOne.getTitle() + "】库存不足！");
            }
            for (MemberDO memberOne : memberList
            ) {
                MemberCouponDO one = new MemberCouponDO();
                one.setCouponId(couponOne.getId());
                one.setMemberId(memberOne.getId());
                one.setMemberCouponStatus(CouponConstants.MemberCouponStatusEnum.NOT_USE.getValue());
                one.setActivityId(0L);
                one.setReceiveChannelDesc("来自：平台送赠");
                one.setCreateBy(memberGetCouponVO.getCreateBy());
                one.setCreateTime(new Date());
                preInsertList.add(one);

                //TODO:模板消息写入
                HashMap<String, String> wxNotifyParam = new HashMap<>();
                if (couponOne.getCouponType() == CouponConstants.TypeEnum.FACE_VALUE.getValue()) {
                    wxNotifyParam.put("discountValueDesc", couponOne.getFaceValue() + "元");
                } else {
                    wxNotifyParam.put("discountValueDesc", couponOne.getDiscount().multiply(BigDecimal.TEN).setScale(1, BigDecimal.ROUND_HALF_UP).toString() + "折");
                }
                wxNotifyParam.put("templateKey", "couponReceive");
                wxNotifyParam.put("shopId", memberOne.getShopId().toString());
                wxNotifyParam.put("openid", memberOne.getOpenid());
                wxNotifyParam.put("title", couponOne.getTitle());
                wxNotifyParam.put("remark", "请及时使用");
                wxNotifyParam.put("useEndTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, couponOne.getUseEndTime()));
                wxNotifyParamList.add(wxNotifyParam);

                //TODO:短信消息写入
                HashMap<String, String> smsNotifyParam = new HashMap<>();
                smsNotifyParam.put("templateKey", "couponReceive");
                smsNotifyParam.put("shopId", memberOne.getShopId().toString());
                smsNotifyParam.put("phone", memberOne.getPhone());
                //2023-02-04 修改赠送优惠券的短信通知内容
                smsNotifyParam.put("smsVar", ",“" + LianLuSmsConstants.SignEnum.DEFAULT.getSign() + "”微信");
                smsNotifyParamList.add(smsNotifyParam);
            }
        }
        backShopCouponMapper.multiInsert(preInsertList);

        //批量消息通知
        for (HashMap<String, String> one : wxNotifyParamList
        ) {
            AsyncManager.me().execute(AsyncFactory.sendWechatTemplateNotify(one));
        }
        //批量短信通知
        for (HashMap<String, String> one : smsNotifyParamList
        ) {
            AsyncManager.me().execute(AsyncFactory.sendSmsNotify(one));
        }
        //优惠券状态更新
        AsyncManager.me().execute(AsyncFactory.refreshCoupon(memberGetCouponVO.getCouponIdStr()));

    }
}
